﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NMF.Utilities;

namespace NMF.Optimizations.Optimizer
{
    public abstract class ModificationGroup
    {
        public ModificationGroup()
        {
            Forbidden = new List<ModificationGroup>();
            Impact = new HashSet<object>();
        }

        public bool Ignore { get; set; }

        public abstract IEnumerable<int> GetIndices();

        public List<ModificationGroup> Forbidden { get; set; }
        public HashSet<object> Impact { get; private set; }

        public abstract IEnumerable<IOptimizationModification> Modifications { get; }
    }

    class SingleModification : ModificationGroup
    {
        public IOptimizationModification Inner { get; set; }
        public int Index { get; set; }

        public SingleModification(IOptimizationModification modification)
        {
            Inner = modification;
            Impact.AddRange(modification.Impact);
        }

        public override IEnumerable<IOptimizationModification> Modifications
        {
            get { yield return Inner; }
        }

        public override IEnumerable<int> GetIndices()
        {
            yield return Index;
        }
    }

    class CompositeModificationGroup : ModificationGroup
    {
        public ModificationGroup Group1 { get; set; }
        public ModificationGroup Group2 { get; set; }

        public CompositeModificationGroup(ModificationGroup group1, ModificationGroup group2)
        {
            Group1 = group1;
            Group2 = group2;

            Impact.AddRange(group1.Impact);
            Impact.AddRange(group2.Impact);
        }

        public override IEnumerable<IOptimizationModification> Modifications
        {
            get { return Group1.Modifications.Concat(Group2.Modifications); }
        }

        public override IEnumerable<int> GetIndices()
        {
            return Group1.GetIndices().Concat(Group2.GetIndices());
        }
    }

}
